\newpage

\section*{Solution}

\begin{enumerate}
    \item Here follows the listing for the first exercise
    \lstset{basicstyle=\scriptsize\sf}
    \lstinputlisting{./src/ex1/main.cpp}
    \lstset{basicstyle=\sf}
    One possible approach to this problem is to introduce a predicate that
    performs the check on the biggest modulus. The predicate is a functor, or a
    function, that takes as input the objects to test and gives a \cpp{bool} as
    output. The \cpp{sort} algorithm needs to iterators to specify the range of
    values on which the algorithm is applied.
	
    \item Here follows the listing for the second exercise
    \lstset{basicstyle=\scriptsize\sf}
    \lstinputlisting{./src/ex2/main.cpp}
    \lstset{basicstyle=\sf}
    The \cpp{find} algorithm finds objects inside containers, so it requires
    that the \cpp{operator==} is implemented for the object type. The algorithm
    returns an iterator to the place where the condition is met, or the
    \cpp{end} iterator if no element in the range satisfies it. It is strongly
    advised to always check if the returned iterator is different from the
    \cpp{end} iterator to see if the find has been successful. In order to
    search the second and third occurrence of the same value, we call again
    \cpp{find} on the subsequence that starts just after the previously found
    iterator, that can be obtained by pre-incrementing the iterator. The
    position in the vector of the iterator can be computed with \cpp{distance}
    function.
		
    \item Here follows the listing for the third exercise
    \lstset{basicstyle=\scriptsize\sf}
    \lstinputlisting{./src/ex3/main.cpp}
    \lstset{basicstyle=\sf}
    The \cpp{count_if} algorithm also requires a function as a input. In this
    case we chose to implement it as a \emph{lambda function}. The function now
    takes only one argument as input. The algorithm applies the function to the
    range defined by the two iterators that are passed to it. The algorithm
    returns the number of occurrences that satisfy the predicate. Note that we
    use a \cpp{const} object in the lambda function, a it is not modified by the
    predicate. The list is initialized with a \cpp{for-range} loop, where we
    note that the current element is marked by \cpp{auto &}, as it must be
    modified in the loop. To print out the list, we use in this case a
    \cpp{stream_iterator} in conjunction with the \cpp{copy} algorithm.
		
    \item Here follows the listing for the forth exercise
    \lstset{basicstyle=\scriptsize\sf}
    \lstinputlisting{./src/ex4/main.cpp}
    \lstset{basicstyle=\sf}
    Also in this case we use a lambda function as the predicate parameter for
    the \cpp{accumulate} algorithm. This algorithm can be invoked also with only
    three parameters, in that case it performs the sum of the elements. The
    predicate as two parameters, the partial sum until that point and the
    current value to be added. The algorithm determines the return type from the
    third parameter, that is the starting value of the accumulation.
		
    \item Here follows the listing for the fifth exercise 
    \lstset{basicstyle=\scriptsize\sf}
    \lstinputlisting{./src/ex5/main.cpp}
    \lstset{basicstyle=\sf}
    First of all we create four empty sets. The first two sets are initialized
    via the \cpp{generate_n} algorithm, that sets the value of the objects
    inside a container using a generator function, that is a lambda function
    in this case. Note that, in order to properly create the sequence, the
    lambda function must use the \cpp{cpp} variable that is defined in the
    containing scope. This is achieved with the \cpp{[&]} definition of the
    lambda, that tells the compiler that inside it every value from outside can
    be used as a reference. The computation of the union and of the intersection
    is performed with the \cpp{set_union} and \cpp{set_intersection} algorithms.
    They take two containers and an iterator to the starting point of the
    receiving container. Since the destination set is empty, we need to
    \emph{convert} the calls that the algorithm would do into insertion. This is
    done with an \cpp{insert_iterator}, that is designed exactly for this
    purpose.
		
    \item Here follows the listing for the sixth exercise 
    \lstset{basicstyle=\scriptsize\sf}
    \lstinputlisting{./src/ex6/main.cpp}
    \lstset{basicstyle=\sf}
    This exercise exemplifies a way to apply boundary conditions. The key of the
    map identifies the flag that is assigned to a given boundary, while the
    value is a pointer to the function that must be applied on that boundary. In
    order to fill the map we use the \cpp{operator[]} method, while we use the
    \cpp{find} method to access them. The \cpp{find} method returns an iterator
    to the corresponding \cpp{pair}, or the \cpp{end} iterator if the key is
    missing. Since the return type is a pointer to a \cpp{pair}, the value can
    be accessed with \cpp{->second}.
	
    \item Here follows the listing for the seventh exercise 
    \lstset{basicstyle=\scriptsize\sf}
    \lstinputlisting{./src/ex7/main.cpp}
    \lstset{basicstyle=\sf}
    The extensive use of \cpp{tuple}s in this example is straightforward. The
    only notes are on the difference between the \cpp{make_tuple} function and
    the \cpp{tie} function. While \cpp{make_pair} generates a tuple starting 
    from a list of elements, so it is used as a right-value, \cpp{tie} is used
    as a left-value to unpack a tuple into a list of elements. The use of
    \cpp{tuple}s can be useful as return value for a function with many outputs,
    as it is the case for our \cpp{Newton::apply}.

\end{enumerate}
